package com.ns.dcjh.utils;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import com.google.gson.Gson;
import com.ns.dcjh.bean.CrashBean;
import com.ns.dcjh.constant.Constant;

import org.json.JSONObject;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CrashHandler implements Thread.UncaughtExceptionHandler {
    public static final String APP_CRASH_PATH = Environment.getExternalStorageDirectory()
            + "/AllHouseSource/crash";

    private CrashHandler() {
    }

    /**
     * 获取CrashHandler实例 ,单例模式
     */
    public static CrashHandler getInstance() {
        return null == crasHandler ? crasHandler = new CrashHandler() : crasHandler;
    }

    /**
     * 初始化
     *
     * @param context 应用上下文
     */
    public void init(Context context) {
        this.context = context;
        // 获取系统默认的UncaughtException处理器
         defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        // 设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * UncaughtException发生时
     */
    public void uncaughtException(Thread thread, Throwable ex) {
        final String crashReport = getCrashReport(context, ex);
        new Thread() {
            public void run() {
                try {
                    Looper.prepare();
                    JSONObject jsonObject = new JSONObject();
                    try {
                        jsonObject.put("user", String.valueOf(SharedPreferencesUtils.getInstance(context)
                                .objectForKey(Constant.SP_KEY_REGISTRATION_ID, "")));
                        jsonObject.put("file", crashReport);
                        jsonObject.put("type", "crashError");
                        jsonObject.put("timestamp", System.currentTimeMillis() / 1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    HttpUtils.post(context,Constant.HOME_URL.replace("/wap","") + "index-tool-saveDebugInfo.html",jsonObject, new HttpCallback(){

                        @Override
                        public void onStart() {

                        }

                        @Override
                        public void onSuccess(String data) {
                        }

                        @Override
                        public void onError(String msg) {
                        }
                    });
                    Log.e("error", crashReport);
                    writeStrToFile(crashReport);
                    Looper.loop();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();

        // 暂停5秒
        try {
            Thread.sleep(2 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if (defaultHandler != null) {
            defaultHandler.uncaughtException(thread, ex);
        } else {
            android.os.Process.killProcess(android.os.Process.myPid());
        }
        System.exit(0);

    }

    public static void writeStrToFile(String string) {
        try {
            File file = new File(APP_CRASH_PATH);
            if (!file.exists()) {
                file.mkdirs();
                file = null;
            }

            FileOutputStream fos = new FileOutputStream(new File(APP_CRASH_PATH + File.separator
                    + formatDate(new Date(System.currentTimeMillis()), 22) + "_crash.txt"));

            Writer os = new OutputStreamWriter(fos, "UTF-8");

            os.write(string);
            os.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     */
    public boolean handleException(Throwable ex) {

        return true;
    }

    /**
     * 获取APP崩溃异常报告
     *
     * @param ex
     * @return
     */
    private String getCrashReport(Context context, Throwable ex) {
        PackageInfo pinfo = getPackageInfo(context);
        StringBuffer exceptionStr = new StringBuffer();
        exceptionStr.append("Version: " + pinfo.versionName + "(" + pinfo.versionCode + ")\n");

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        pw.flush();

        exceptionStr.append("Exception: " + sw.toString() + "\n");

        StackTraceElement[] elements = ex.getStackTrace();
        for (int i = 0; i < elements.length; i++) {
            exceptionStr.append(elements[i].toString() + "\n");
        }
        return exceptionStr.toString();
    }

    /**
     * 获取App安装包信息
     *
     * @return
     */
    private PackageInfo getPackageInfo(Context context) {
        PackageInfo info = null;
        try {
            info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
        }
        if (info == null)
            info = new PackageInfo();
        return info;
    }

    // 系统默认的UncaughtException处理类
    private Thread.UncaughtExceptionHandler defaultHandler;
    // CrashHandler实例
    private static CrashHandler crasHandler;
    // 程序的Context对象
    private Context context;

    /**
     * 将指定日期转化为指定格式
     *
     * @param date
     * @param num
     * @return
     */
    public static String formatDate(Date date, int num) {
        if (null == date) {
            date = new Date();
        }

        switch (num) {
            case 5:
                return getSdf("MM-dd").format(date);
            case 6:
                return getSdf("yyyyMM").format(date);
            case 7:
                return getSdf("yyyy-MM").format(date);
            case 8:
                return getSdf("yyyyMMdd").format(date);
            case 10:
                return getSdf("yyyy-MM-dd").format(date);
            case 14:
                return getSdf("yyyyMMddHHmmss").format(date);
            case 16:
                return getSdf("yyyy-MM-dd HH:mm").format(date);
            case 18:
                return getSdf("yyyyMMddHHmmssSSSS").format(date);
            case 19:
                return getSdf("yyyy-MM-dd HH:mm:ss").format(date);
            case 20:
                return getSdf("HH:mm").format(date);
            case 21:
                return getSdf("yyyy年MM月dd日 HH:mm").format(date);
            case 22:
                return getSdf("yyyy_MM_dd HH_mm").format(date);
            default:
                return getSdf("yyyy-MM-dd HH:mm:ss").format(date);
        }
    }

    public static SimpleDateFormat getSdf(String pattern) {
        if (null == pattern) {
            return null;
        } else {
            return new SimpleDateFormat(pattern);
        }
    }
}
